using System;
using System.Collections;
using UnityEngine;

public class Entity : MonoBehaviour
{
    public static event Action OnFlipped = delegate { };//实体翻转事件，更新血条不翻转
    public StateMachine stateMachine;
    #region Compontent
    public Animator animator { get; private set; }
    public Rigidbody2D rb { get; private set; }
    public Entity_Stat entityStat { get; private set; }
    public Entity_Combat combat { get; private set; }
    #endregion

    public int facingDir = 1; //角色朝向距离
    protected bool facingRight = true; //角色是否朝向右边


    [Header("-----Collision Info-----")]
    [SerializeField] protected Transform groundCheck; //地面检测点
    [SerializeField] protected Transform firstWallCheck; //墙壁检测点
    [SerializeField] protected Transform secondWallCheck; //墙壁检测点
    [SerializeField] protected float groundCheckDistance; //地面检测距离
    [SerializeField] protected float wallCheckDistance; //墙壁检测距离
    public LayerMask whatIsGround; //层级
    public bool IsGround;
    public bool IsWall;
    private Coroutine knockBackCoroutine;
    private Coroutine slowDownEntityCoroutine;
    protected virtual void Awake()
    {
        animator = GetComponentInChildren<Animator>();
        rb = GetComponent<Rigidbody2D>();
        entityStat = GetComponent<Entity_Stat>();
        combat = GetComponent<Entity_Combat>();
        stateMachine = new();
    }
    protected virtual void Start()
    {

    }
    protected virtual void Update()
    {
        HandleCollisionDetection();
    }
    
    //设置物理速度为0
    public void SetVelocityZero() => rb.velocity = Vector2.zero;
    //设置物理速度
    public void SetVelocity(float xVelocity, float yVelocity)
    {
        rb.velocity = new Vector2(xVelocity, yVelocity);
        HandleFlip(rb.velocity.x);
    }
    //开启击退协程
    public void StartKnockBackCoroutine(Vector2 knockBack, float duration)
    {
        if (knockBackCoroutine != null)
        {
            StopCoroutine(KnockBackCo(knockBack, duration));
        }
        knockBackCoroutine = StartCoroutine(KnockBackCo(knockBack, duration));
    }
    public IEnumerator KnockBackCo(Vector2 knockBack, float duration)
    {
        rb.velocity = knockBack;
        yield return new WaitForSeconds(duration);
        //将速度设置为零
        SetVelocityZero();
    }
    //角色翻转
    public virtual void Flip()
    {
        facingDir = -facingDir;
        facingRight = !facingRight;
        transform.Rotate(0, 180, 0);
        OnFlipped?.Invoke();
    }
    //角色翻转控制器
    public virtual void HandleFlip(float _x)
    {
        if ((_x > 0 && !facingRight) || (_x < 0 && facingRight))
        {
            Flip();
        }
    }
    //实体受到冰元素攻击减速
    public virtual void StartSlowdownEntityCo(float duration, float slowMultiplier,bool canOverrideCo = false)
    {
        if (slowDownEntityCoroutine != null)
        {
            if (canOverrideCo)
                StopCoroutine(slowDownEntityCoroutine);
            else
                return;
        }
        slowDownEntityCoroutine = StartCoroutine(SlowDownEntityCo(duration, slowMultiplier));
    }
    public virtual void StopSlowdownEntityCo()
    {
        slowDownEntityCoroutine = null;
    }
    //冰元素攻击减速协程
    protected virtual IEnumerator SlowDownEntityCo(float duration, float slowMultiplier)
    {
        yield return null;
    }
    //实体死亡
    public virtual void EntityDead()
    {

    }
    private void HandleCollisionDetection()
    {
        //检测是否触碰地面
        IsGround = Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);
        //检测是否触碰墙壁
        if (secondWallCheck != null)
        {
            IsWall = Physics2D.Raycast(firstWallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround)
                && Physics2D.Raycast(secondWallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);
        }
        else
        {
            IsWall = Physics2D.Raycast(firstWallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);
        }
    }
    //得到动画触发器（玩家动画事件脚本调用）（在动画播放完后通过动画帧事件调用）
    public void CurrentAnimatorTrigger() => stateMachine.currentState.AnimatorTrigger();
    protected virtual void OnDrawGizmos()
    {
        Gizmos.DrawLine(groundCheck.position, new Vector2(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));
        Gizmos.DrawLine(firstWallCheck.position, new Vector2(firstWallCheck.position.x + wallCheckDistance, firstWallCheck.position.y));
        if (secondWallCheck != null)
        {
            Gizmos.DrawLine(secondWallCheck.position, new Vector2(secondWallCheck.position.x + wallCheckDistance, secondWallCheck.position.y));
        }
    }
}
